#include "Tools.h"

#include <gtk/gtk.h>
#include <stdbool.h>
#include <stdio.h>

uint8 code[14] = {0x3f,  // 0
                  0x06,  // 1
                  0x5b,  // 2
                  0x4f,  // 3
                  0x66,  // 4
                  0x6d,  // 5
                  0x7d,  // 6
                  0x07,  // 7
                  0x7f,  // 8
                  0x6f,  // 9
                  0x40,  // -
                  0x00,  //
                  0x79,  // E
                  0x00}; //

void
_digital_tube_push (uint8 array_8[])
{
        uint8 tmp;
        bool  has_dot;
        system ("clear");
        printf ("  = = = = = = = =\n");
        printf ("[ ");
        for (int i = 7, j = 0; i >= 0; --i) {
                tmp     = array_8[i];
                has_dot = tmp & 0x80;
                tmp &= 0x7f;
                for (j = 0; j < 14; ++j)
                        if (code[j] == tmp)
                                break;
                if (j < 10)
                        tmp = j + '0';
                else if (j == 10)
                        tmp = '-';
                else if (j == 12)
                        tmp = 'E';
                else if (j == 14 && tmp == 0x50)
                        tmp = 'r';
                else if (j == 14 && tmp == 0x5c)
                        tmp = 'o';
                else
                        tmp = ' ';
                printf ("%c", (char)tmp);
                if (has_dot)
                        printf (".");
                else
                        printf (" ");
        }
        printf ("]\n");
        printf ("  = = = = = = = =\n");
}

static GThread*        th = NULL;
static GtkApplication* gapp;
static ButtonType      btn0 = BUTTON_TYPE_NONE;

static void
button_action (GtkButton* btn, gpointer data G_GNUC_UNUSED)
{
        const char* buf;
        buf = gtk_button_get_label (btn);
        switch (buf[0]) {
        case '0':
                btn0 = 0;
                break;
        case '1':
                btn0 = 1;
                break;
        case '2':
                btn0 = 2;
                break;
        case '3':
                btn0 = 3;
                break;
        case '4':
                btn0 = 4;
                break;
        case '5':
                btn0 = 5;
                break;
        case '6':
                btn0 = 6;
                break;
        case '7':
                btn0 = 7;
                break;
        case '8':
                btn0 = 8;
                break;
        case '9':
                btn0 = 9;
                break;
        case '.':
                btn0 = BUTTON_TYPE_DOT;
                break;
        case '=':
                btn0 = BUTTON_TYPE_EQU;
                break;
        case '/':
                btn0 = BUTTON_TYPE_DIV;
                break;
        case '*':
                btn0 = BUTTON_TYPE_MUL;
                break;
        case '-':
                btn0 = BUTTON_TYPE_SUB;
                break;
        case '+':
                btn0 = BUTTON_TYPE_ADD;
                break;
        case 'C':
                btn0 = BUTTON_TYPE_CLS;
                break;
        case '<':
                btn0 = BUTTON_TYPE_LEFT;
                break;
        case '>':
                btn0 = BUTTON_TYPE_RIGHT;
                break;
        default:
                btn0 = BUTTON_TYPE_NONE;
                break;
        }
}

static void
button_surface_control (GtkApplication* app, gpointer data G_GNUC_UNUSED)
{
        GtkWidget *window, *grid, *btn[20];

        window  = gtk_application_window_new (app);
        grid    = gtk_grid_new ();

        btn[0]  = gtk_button_new_with_label ("7");
        btn[1]  = gtk_button_new_with_label ("8");
        btn[2]  = gtk_button_new_with_label ("9");
        btn[3]  = gtk_button_new_with_label ("/");
        btn[4]  = gtk_button_new_with_label ("4");
        btn[5]  = gtk_button_new_with_label ("5");
        btn[6]  = gtk_button_new_with_label ("6");
        btn[7]  = gtk_button_new_with_label ("*");
        btn[8]  = gtk_button_new_with_label ("1");
        btn[9]  = gtk_button_new_with_label ("2");
        btn[10] = gtk_button_new_with_label ("3");
        btn[11] = gtk_button_new_with_label ("-");
        btn[12] = gtk_button_new_with_label (".");
        btn[13] = gtk_button_new_with_label ("0");
        btn[14] = gtk_button_new_with_label ("=");
        btn[15] = gtk_button_new_with_label ("+");
        btn[16] = gtk_button_new_with_label ("C");
        btn[17] = gtk_button_new_with_label (" ");
        btn[18] = gtk_button_new_with_label ("<");
        btn[19] = gtk_button_new_with_label (">");

        for (int y = 0, i = 0; y < 5; ++y) {
                for (int x = 0; x < 4; ++x, ++i) {
                        gtk_grid_attach (GTK_GRID (grid), btn[i], x, y, 1, 1);
                        g_signal_connect (btn[i],
                                          "clicked",
                                          G_CALLBACK (button_action),
                                          NULL);
                }
        }

        gtk_window_set_child (GTK_WINDOW (window), grid);

        gtk_window_present (GTK_WINDOW (window));
}

static gpointer
button_surface_control_main (gpointer data)
{
        char* argv = "a.out";
        gapp       = gtk_application_new ("org.example.com",
                                    G_APPLICATION_DEFAULT_FLAGS);
        g_signal_connect (gapp,
                          "activate",
                          G_CALLBACK (button_surface_control),
                          NULL);
        g_application_run (G_APPLICATION (gapp), 1, &argv);
        g_object_unref (gapp);

        btn0 = BUTTON_TYPE_QUIT;
        return NULL;
}

ButtonType
button_get_type (void)
{
        ButtonType tmp;
        if (!th) {
                th = g_thread_new ("surface",
                                   button_surface_control_main,
                                   NULL);
        }
retry:
        /*此处：软件意义上的消抖，无此代码运行有 Bug*/
        g_usleep (100000);
        if (btn0 != BUTTON_TYPE_NONE) {
                tmp  = btn0;
                btn0 = BUTTON_TYPE_NONE;
                return tmp;
        }
        if (btn0 == BUTTON_TYPE_QUIT) {
                g_thread_join (th);
                return btn0;
        }
        goto retry;
}
